<template>
	<div class="play-audio">
		<h2 style="text-align: center;">播放页面</h2>
		<div style="text-align: center;">
			<label for="name">接收人：</label>
			<input type="text" id="name" v-model="toUserId" class="form-control" />
		</div>
		<div class="main-box">
			本地：
			<video ref="localVideo" class="video" autoplay="autoplay"></video>

			远程：
			<video ref="remoteVideo" style="margin-left: 20px;" class="video" height="500px"
				autoplay="autoplay"></video>
		</div>
		<div>
			<el-button @click="requestConnect()" ref="callBtn">开始对讲</el-button>
			<el-button @click="hangupHandle()" ref="hangupBtn">结束对讲</el-button>
		</div>


		<div style="text-align: center;" v-if="showCall">
			<button id="hangup" class="hangup" onclick="hangupVideoButton()">挂断</button>
			<button id="accept" class="accept" onclick="acceptVideoButton()">接受</button>
		</div>
	</div>

</template>

<el-dialog :title="'提示'" :visible.sync="dialogVisible" width="30%">
	<span>{{ toUserId + '请求连接!' }}</span>
	<span slot="footer" class="dialog-footer">
		<!-- <el-button @click="handleClose">取 消</el-button> -->
		<!-- <el-button type="primary" @click="dialogVisibleYes">确 定</el-button> -->
	</span>
</el-dialog>

<script>
	export default {
		data() {
			return {
				toUserId: null,
				localStream: null,
				remoteStream: null,
				localVideo: null,
				remoteVideo: null,
				PeerConnection: null,
				dialogVisible: false,
				msg: '',
				yourConn: null,
				isCaller: false,
				userInfo: {
					userId: localStorage.getItem('userId'),
					userName: localStorage.getItem('userName')
				},
				showCall: false,
			}
		},
		mounted() {
			this.remoteVideo = this.$refs.remoteVideo
			this.localVideo = this.$refs.localVideo
		},
		/**
		 * 监听发送过来的聊天消息
		 */
		watch: {
			'$store.state.chatMessageStr'(newVal, oldVal) {
				//获取消息对象
				// let message = JSON.parse(newVal);
				let message = newVal;
				console.log("接受到的信息--》", message);

				if (message.contentType == "call_start") {
					console.log("被叫方准备初始化webRtc--->");
					//初始化webrtc
					this.initWebRTC();
					setTimeout(() => {
						console.log("被叫方初始化webRtc完毕--->");
					 console.log("被叫方初始化webRtc完毕--this.yourConn->", this.yourConn);
					}, 3000);



					//判断是否为推送过来的信令			
				} else if (message.contentType == "candidate") {
					//设置信令的应答
					this.toUserId = message.from
					console.log("this.yourConn--》", this.yourConn);
					console.log("message.content--》", message.content);
					console.log("message.content-candidate-》", message.content.candidate);
					//处理ICE备选
					this.yourConn.addIceCandidate(new RTCIceCandidate(message.content));
				} else if (message.contentType == "text") {
					//弹出提示对话框
					console.log("被叫方接收到视频请求--->", message);

					this.$confirm(message.content, '提示', {
						confirmButtonText: '接受',
						cancelButtonText: '挂断',
						type: 'warning'
					}).then(() => {
						//接受通话
						this.acceptVideoButton(message);
					}).catch(() => {
						//挂断通话
						this.hangupVideoButton(message);
					});


				} else if (message.contentType == "call_back") {
					console.log("主叫方接收到同意视频请求--->", message);

					//弹出提示对话框
					this.$alert(message.to + "接受了你的视频通话", '公告', {
						confirmButtonText: '确定',
					});
					//处理视频通话请求回调
					this.handleCallBack(message);

				} else if (message.contentType == "offer") {

					//处理视频通话请求回调
					this.handleOffer(message);

				} else if (message.contentType == "answer") {

					//处理视频通话应答
					this.handleAnswer(message);

				}


			}
		},
		methods: {


			//发起视频通话
			requestConnect() {

				if (!this.toUserId) {
					alert('请输入对方id')
					return false
				}

				//设置当前用户为主叫
				this.isCaller = true;
				console.log("主叫方准备开始初始化webrtc-->");
				//初始化webrtc
				this.initWebRTC();

				setTimeout(() => {
					//推送通话信息
					let mesg1 = {
						from: this.userInfo.userId,
						to: this.toUserId,
						contentType: "call_start",
						content: ""
					}
					console.log("call_start：", mesg1);
					this.$websocket.Send(mesg1);



					//推送通话信息
					let mesg = {
						from: this.userInfo.userId,
						to: this.toUserId,
						contentType: "text",
						content: this.userInfo.userName + "请求与你视频通话"
					}
					console.log("推送通话信息：", mesg);
					this.$websocket.Send(mesg);
				}, 3000);



			},
			//初始化webrtc
			initWebRTC() {
				console.log("当前PeerConnection--->", this.PeerConnection);

				if (this.PeerConnection !== null && this.PeerConnection !== undefined) {
					return;
				}


				this.PeerConnection = (window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window
					.RTCPeerConnection || undefined);

				console.log("赋值后PeerConnection--->", this.PeerConnection);
				//  RTCSessionDescription = (window.webkitRTCSessionDescription || window.mozRTCSessionDescription || window.RTCSessionDescription || undefined);

				if (navigator.mediaDevices === undefined) {
					navigator.mediaDevices = {};
				}
				if (navigator.mediaDevices.getUserMedia === undefined) {
					navigator.mediaDevices.getUserMedia = function(constraints) {
						var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
						if (!getUserMedia) {
							return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
						}
						return new Promise(function(resolve, reject) {
							getUserMedia.call(navigator, constraints, resolve, reject);
						});
					}
				}

				var mediaOpts = {
					// audio: audioVideoDevices.audioinput || audioVideoDevices.audiooutput,
					audio: true,
					//判断如果是视频通话就调用前置摄像头，facingMode: "user"调用前置摄像头，如果不是视屏通话就不使用摄像头
					video: {
						facingMode: "user",
					}
				}

				navigator.mediaDevices.getUserMedia(mediaOpts)
					.then(stream => {
						// 成功获取媒体流后调用成功回调函数
						this.successFunc(stream);
					}).catch(error => {
						// 获取媒体流失败时调用失败回调函数
						this.errorFunc(error);
					});



			},

			//获取摄像头权限成功时执行的回调
			successFunc(myStream) {
				let _that = this;
				console.log("摄像头权限获取成功--->", myStream);

				//播放本地摄像头捕捉到的画面
				this.localVideo.srcObject = myStream;

				//using Google public stun server,turn中继服务器需要自己搭建，可参考网上coturn搭建教程
				//此处指定了服务器，是 Google 的 STUN 服务器，
				var configuration = {
					"iceServers": [{
						'urls': 'stun:stun.l.google.com:19302'
					}]
				};



				//在浏览器之间建立点对点的连接
				this.yourConn = new this.PeerConnection(configuration);

				console.log("主叫方this.yourConn--->", this.yourConn);

				// 添加流到对等连接，这里stream 是本地摄像头或麦克风捕获的音视频流，使用 addStream 方法将这个流添加到对等连接中，以便与远程对等连接共享
				this.yourConn.addStream(myStream);

				//当远程用户向对等连接添加流时，将触发这个事件，并将流设置为远程视频元素 remoteVideo 的源对象，以显示远程用户的视频。即对方接受视频通过后就会触发当前方法
				this.yourConn.onaddstream = function(e) {
					console.log("被叫用户向对等连接添加流--this.remoteVideo->", _that.remoteVideo);
					console.log("被叫用户向对等连接添加流--->", e.stream);

					//将远程流显示到页面
					_that.remoteVideo.srcObject = e.stream;
				};


				// 在发现新的 ICE 候选时执行的回调
				this.yourConn.onicecandidate = function(event) {
					//是否存在 ICE 候选
					if (event.candidate) {
						//如果存在 ICE 候选，则通过 WebSocket 发送 ICE 候选信息给对端

						let mesg = {
							from: _that.userInfo.userId,
							to: _that.toUserId,
							contentType: "candidate",
							content: event.candidate,

						}




						console.log("发送ICE候选--->", mesg);
						_that.$websocket.Send(mesg);
					}
				};
			},
			//获取摄像头权限失败时执行的回调
			errorFunc(err) {
				console.log("主叫方获取摄像头权限失败--->", err);
				if ("NotFoundError" == err.name) {
					alert("设备不具备视频、音频条件或没有音视频权限");
				} else {

					alert(err.name);
				}

			},



			//结束通话
			hangupHandle() {

			},
			//接受视频请求
			acceptVideoButton(message) {

				this.toUserId = message.from;
				var data = {
					contentType: "call_back",
					to: this.toUserId,
					from: this.userInfo.userId,
					content: "accept"
				}
				console.log("被叫方发送接受视频请求--》", data);
				this.$websocket.Send(data);



			},


			//挂断视频聊天
			hangupVideoButton(message) {
				let data = {
					contentType: "leave",
					to: this.toUserId,
					from: this.userInfo.userId,
					content: ""
				}
				this.$websocket.Send(data);
				//关闭视频流和PeerConnection
				this.closeVideoStream();
			},
			//关闭视频流和PeerConnection
			closeVideoStream() {
				try {
					this.localVideo.srcObject.getTracks()[0].stop();
					this.localVideo.srcObject.getTracks()[1].stop();
					this.remoteVideo.srcObject.getTracks()[0].stop();
					this.remoteVideo.srcObject.getTracks()[1].stop();

				} catch (e) {
					console.log(e)

				} finally {

					this.yourConn.close();
					this.PeerConnectionPeerConnection = null;
					this.yourConn.onicecandidate = null;
					this.yourConn.onaddstream = null;

					this.isCaller = false;
				}

			},
			//处理视频请求的响应
			handleCallBack(data) {
				console.log("主叫方开始处理同意视频请求后的响应--- this.yourConn 》", this.yourConn);
				let _that = this;

				//接受视频
				if (data.content == "accept") {
					//,这个回调函数会在 SDP offer 创建成功后被调用,生成本地端的会话描述（SDP)
					this.yourConn.createOffer(function(offer) {
						let sendData = {
							from: _that.userInfo.userId,
							to: _that.toUserId,
							contentType: "offer",
							content: offer
						};
						console.log("offer--->", sendData);
						_that.$websocket.Send(sendData);


						//将这个 SDP offer 设置为本地端的会话描述
						_that.yourConn.setLocalDescription(offer);
					}, function(error) {
						alert("Error when creating an offer");
					});

				} else {
					//拒绝视频
					//关闭视频流和PeerConnection
					this.closeVideoStream();

				}

			},
			//处理offer请求
			handleOffer(data) {
				let _that = this;
				console.log("被叫方接受到offer--- this.yourConn 》", this.yourConn);
				console.log("被叫方接受到data----- data-- 》", data);
				console.log("data.content------ 》", data.content);
				console.log("data.content.sdp------ 》", data.content.sdp);



				this.yourConn.setRemoteDescription(new RTCSessionDescription(data.content));

				//create an answer to an offer
				this.yourConn.createAnswer(function(answer) {
					_that.yourConn.setLocalDescription(answer);


					let answerData = {
						from: _that.userInfo.userId,
						to: _that.toUserId,
						contentType: "answer",
						content: answer
					};
					console.log("创建应答数据----- answerData 》", answerData);


					_that.$websocket.Send(answerData);

				}, function(error) {
					alert("Error when creating an answer");
				});
			},
			//处理应答
			handleAnswer(data) {
				console.log("主叫方接受到应答----- this.yourConn-- 》", this.yourConn);
				console.log("主叫方接受到应答----- data-- 》", data);
				this.yourConn.setRemoteDescription(new RTCSessionDescription(data.content));

			}

		}

	}
</script>
<style lang="css">
	.spreadsheet {
		padding: 0 10px;
		margin: 20px 0;
	}

	.main-box {
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: center;
	}
</style>
